package com.nadostar.extensions.util;

import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.EntityReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
import org.w3c.dom.UserDataHandler;

/**
 * @author LEESUNG
 * 
 */
public final class Document implements org.w3c.dom.Document {
	private org.w3c.dom.Document document;
	/**
	 * document의 String 표현에 대한 hashcode를 캐싱한다.
	 */
	private int hash; // Default to 0

	private static final String EMPTY_STRING = "";
	/**
	 * Document의 toString() 에 대한 값을 캐싱한다.
	 */
	private String toString;

	Document(org.w3c.dom.Document document) {
		this.document = document;
	}

	public String toString() {
		String self = toString;
		if (self == null) {
			self = (document == null) ? EMPTY_STRING : XMLDOMUtil.printXML(
					document).toString();
			toString = self;
		}
		return self;
	}

	public int hashCode() {
		int h = hash;
		if (h == 0) {
			h = (document == null) ? 0 : document.toString().hashCode();
			hash = h;
		}
		return h;
	}

	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Document other = (Document) obj;
		if (document == null) {
			if (other.document != null)
				return false;
		} else if (!document.toString().equals(other.document.toString())) {

			return false;
		}
		return true;
	}

	public Node adoptNode(Node arg0) throws DOMException {
		return this.document.adoptNode(arg0);
	}

	public Attr createAttribute(String arg0) throws DOMException {
		return this.document.createAttribute(arg0);
	}

	public Attr createAttributeNS(String arg0, String arg1) throws DOMException {
		return this.document.createAttributeNS(arg0, arg1);
	}

	public CDATASection createCDATASection(String arg0) throws DOMException {
		return this.document.createCDATASection(arg0);
	}

	public Comment createComment(String arg0) {
		return this.document.createComment(arg0);
	}

	public DocumentFragment createDocumentFragment() {
		return this.document.createDocumentFragment();
	}

	public Element createElement(String arg0) throws DOMException {
		return this.document.createElement(arg0);
	}

	public Element createElementNS(String arg0, String arg1)
			throws DOMException {
		return this.document.createElementNS(arg0, arg1);
	}

	public EntityReference createEntityReference(String arg0)
			throws DOMException {
		return this.document.createEntityReference(arg0);
	}

	public ProcessingInstruction createProcessingInstruction(String arg0,
			String arg1) throws DOMException {
		return this.document.createProcessingInstruction(arg0, arg1);
	}

	public Text createTextNode(String arg0) {
		return this.document.createTextNode(arg0);
	}

	public DocumentType getDoctype() {
		return this.document.getDoctype();
	}

	public Element getDocumentElement() {
		return this.document.getDocumentElement();
	}

	public String getDocumentURI() {
		return this.document.getDocumentURI();
	}

	public DOMConfiguration getDomConfig() {
		return this.document.getDomConfig();
	}

	public Element getElementById(String arg0) {
		return this.document.getElementById(arg0);
	}

	public NodeList getElementsByTagName(String arg0) {
		return this.document.getElementsByTagName(arg0);
	}

	public NodeList getElementsByTagNameNS(String arg0, String arg1) {
		return this.document.getElementsByTagNameNS(arg0, arg1);
	}

	public DOMImplementation getImplementation() {
		return this.document.getImplementation();
	}

	public String getInputEncoding() {
		return this.document.getInputEncoding();
	}

	public boolean getStrictErrorChecking() {
		return this.document.getStrictErrorChecking();
	}

	public String getXmlEncoding() {
		return this.document.getXmlEncoding();
	}

	public boolean getXmlStandalone() {
		return this.document.getXmlStandalone();
	}

	public String getXmlVersion() {
		return this.document.getXmlVersion();
	}

	public Node importNode(Node arg0, boolean arg1) throws DOMException {
		return this.document.importNode(arg0, arg1);
	}

	public void normalizeDocument() {
		this.document.normalizeDocument();
	}

	public Node renameNode(Node arg0, String arg1, String arg2)
			throws DOMException {
		return this.document.renameNode(arg0, arg1, arg2);
	}

	public void setDocumentURI(String arg0) {
		this.document.setDocumentURI(arg0);
	}

	public void setStrictErrorChecking(boolean arg0) {
		this.document.setStrictErrorChecking(arg0);
	}

	public void setXmlStandalone(boolean arg0) throws DOMException {
		this.document.setXmlStandalone(arg0);
	}

	public void setXmlVersion(String arg0) throws DOMException {
		this.document.setXmlVersion(arg0);
	}

	public Node appendChild(Node arg0) throws DOMException {
		return this.document.appendChild(arg0);
	}

	public Node cloneNode(boolean arg0) {
		return this.document.cloneNode(arg0);
	}

	public short compareDocumentPosition(Node arg0) throws DOMException {
		return this.document.compareDocumentPosition(arg0);
	}

	public NamedNodeMap getAttributes() {
		return this.document.getAttributes();
	}

	public String getBaseURI() {
		return this.document.getBaseURI();
	}

	public NodeList getChildNodes() {
		return this.document.getChildNodes();
	}

	public Object getFeature(String arg0, String arg1) {
		return this.document.getFeature(arg0, arg1);
	}

	public Node getFirstChild() {
		return this.document.getFirstChild();
	}

	public Node getLastChild() {
		return this.document.getLastChild();
	}

	public String getLocalName() {
		return this.document.getLocalName();
	}

	public String getNamespaceURI() {
		return this.document.getNamespaceURI();
	}

	public Node getNextSibling() {
		return this.document.getNextSibling();
	}

	public String getNodeName() {
		return this.document.getNodeName();
	}

	public short getNodeType() {
		return this.document.getNodeType();
	}

	public String getNodeValue() throws DOMException {
		return this.document.getNodeValue();
	}

	public org.w3c.dom.Document getOwnerDocument() {
		return this.document.getOwnerDocument();
	}

	public Node getParentNode() {
		return this.document.getParentNode();
	}

	public String getPrefix() {
		return this.document.getPrefix();
	}

	public Node getPreviousSibling() {
		return this.document.getPreviousSibling();
	}

	public String getTextContent() throws DOMException {
		return this.document.getTextContent();
	}

	public Object getUserData(String arg0) {
		return this.document.getUserData(arg0);
	}

	public boolean hasAttributes() {
		return this.document.hasAttributes();
	}

	public boolean hasChildNodes() {
		return this.document.hasChildNodes();
	}

	public Node insertBefore(Node arg0, Node arg1) throws DOMException {
		return this.document.insertBefore(arg0, arg1);
	}

	public boolean isDefaultNamespace(String arg0) {
		return this.document.isDefaultNamespace(arg0);
	}

	public boolean isEqualNode(Node arg0) {
		return this.document.isEqualNode(arg0);
	}

	public boolean isSameNode(Node arg0) {
		return this.document.isSameNode(arg0);
	}

	public boolean isSupported(String arg0, String arg1) {
		return this.document.isSupported(arg0, arg1);
	}

	public String lookupNamespaceURI(String arg0) {
		return this.document.lookupNamespaceURI(arg0);
	}

	public String lookupPrefix(String arg0) {
		return this.document.lookupPrefix(arg0);
	}

	public void normalize() {
		this.document.normalize();
	}

	public Node removeChild(Node arg0) throws DOMException {
		return this.document.removeChild(arg0);
	}

	public Node replaceChild(Node arg0, Node arg1) throws DOMException {
		return this.document.replaceChild(arg0, arg1);
	}

	public void setNodeValue(String arg0) throws DOMException {
		this.document.setNodeValue(arg0);
	}

	public void setPrefix(String arg0) throws DOMException {
		this.document.setPrefix(arg0);
	}

	public void setTextContent(String arg0) throws DOMException {
		this.document.setTextContent(arg0);

	}

	public Object setUserData(String arg0, Object arg1, UserDataHandler arg2) {
		return this.document.setUserData(arg0, arg1, arg2);
	}
}
